package com.ibeetl.code.ch04.template;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Template {

	List<Token> tokens;

	public Template(List<Token> tokens) {
		this.tokens = tokens;
	}

	public final String render(Writer out, Object... args) throws IOException {
		Context ctx = new Context(out, args);
		List<Token> locals = tokens;
		int size = locals.size();
		for (int i = 0; i < size; i++) {
			Token token = locals.get(i);
			token.render(ctx);
		}
		return out.toString();
	}


	static Map<String, Template> cache = new ConcurrentHashMap<>();

	public static Template getTemplate(String pattern) {
		Template template = cache.get(pattern);
		if (template != null) {
			return template;
		}

		template = parse(pattern);
		cache.put(pattern, template);
		return template;
	}

	protected static Template parse(String pattern) {

		int index = -1;
		int start = 0;
		int varIndex = 0;
		List<Token> list = new ArrayList<>();
		while ((index = pattern.indexOf("{}", start)) != -1) {
			String text = pattern.substring(start, index);
			Token textToken = new StaticTextToken(text);
			start = index + 2;
			VarToken varToken = new VarToken(varIndex++);
			list.add(textToken);
			list.add(varToken);
		}

		if (start < pattern.length()) {
			String text = pattern.substring(start);
			Token textToken = new StaticTextToken(text);
			list.add(textToken);
		}
		Template template = new Template(list);
		return template;
	}

	public List<Token> getTokens() {
		return tokens;
	}
}
